package com.leyantech.ecp.agenx.web.handler;

import com.leyantech.ecp.agenx.common.config.Constants;
import com.leyantech.ecp.agenx.common.config.MessageAddress;

import com.ctrip.framework.apollo.ConfigService;
import com.google.inject.Inject;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.RequestOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.core.spi.cluster.RegistrationInfo;
import io.vertx.ext.web.RoutingContext;
import io.vertx.spi.cluster.zookeeper.impl.SubsMapHelper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.curator.framework.CuratorFramework;

import java.util.List;

/**
 * @author eahau, {@literal <eahau@foxmail.com>}
 * @date 2023-02-17.
 */
@Slf4j
public class AdminHandler implements Handler<RoutingContext> {

  private final HttpClient httpClient;

  private final CuratorFramework curator;

  @Inject
  public AdminHandler(HttpClient httpClient, CuratorFramework curator) {
    this.httpClient = httpClient;
    this.curator = curator;
  }

  @SneakyThrows
  @Override
  public void handle(RoutingContext context) {
    final String auth = context.request().getHeader("token");

    final String adminAuth = ConfigService.getAppConfig().getProperty("admin.auth", "");

    if (adminAuth.isEmpty() || !adminAuth.equals(auth)) {
      context.response()
          .setStatusCode(401)
          .end();
      return;
    }

    final JsonObject body = context.body().asJsonObject();

    final String content = body.getJsonObject("text").getString("content", "").trim();

    if ("HealthCheck".equals(content)) {
      final String ping = new JsonObject().put("header", new JsonObject().put("fn", "Ping"))
          .toString();
      final DeliveryOptions deliveryOptions = new DeliveryOptions().addHeader("type", "cmd");
      final EventBus eventBus = context.vertx().eventBus();

      final List<String> subsList = curator.getChildren().forPath("/__vertx.subs");

      for (String address : subsList) {
        if (StringUtils.countMatches(address, '.') != 2) {
          continue;
        }
        eventBus.request(address, ping, deliveryOptions)
            .onSuccess(message -> {
              final Object messageBody = message.body();
              log.info("received messageBody {} {}", address, messageBody);
              if ("Closed".equals(messageBody)) {
                log.info("removeVertxSubs {}", address);
                removeVertxSubs(address);
              }
            });
      }

      context.end();
      return;
    }

    final String webhook = body.getString("sessionWebhook");

    final String[] sidAndAid = content.split("\\.");

    for (String s : sidAndAid) {
      if (!StringUtils.isNumeric(s)) {
        context.response()
            .setStatusCode(403)
            .end();

        sendDingTalk(webhook,
            "{\"text\":{\"content\":\"客服踢下线失败，只支持 {sid} 或 {sid}.{aid} 格式，示例：110 或 110.10086\"},\"msgtype\":\"text\"}");
        return;
      }
    }

    final String senderNick = body.getString("senderNick");

    final String conversationTitle = body.getString("conversationTitle");

    log.info("来自 {} 的 {} KickOut {}", conversationTitle, senderNick, content);

    final JsonObject cmd = new JsonObject()
        .put("header", new JsonObject().put("fn", "KickOut"));

    final DeliveryOptions deliveryOptions = new DeliveryOptions().addHeader("type", "cmd");

    final String address = MessageAddress.toConnector(content);
    context.vertx()
        .eventBus()
        .publish(address, cmd.toString(), deliveryOptions);

    final String kibanaUrl = String.format(
        "https://nta-kibana.infra.leyantech.com/app/kibana#/discover?_a=(columns:!(appname,level,loggerName,message),index:hot-app-log-%s,query:(language:kuery,query:'appname:\"ecp-agenx-pdd\" AND procname:\"connector\" AND \"ws closed %s\"'))",
        Constants.ENV,
        String.join(" ", sidAndAid)
    );

    final String text = String.format("已通知客服 %s 下线，请查看日志确认", content);
    sendDingTalk(webhook,
        new JsonObject()
            .put("msgtype", "link")
            .put("link",
                new JsonObject()
                    .put("title", "客服下线日志链接")
                    .put("text", text)
                    .put("messageUrl", kibanaUrl)
            )
            .toString()
    );

    removeVertxSubs(address);

    context.end();
  }

  private void sendDingTalk(String webhook, String message) {
    final RequestOptions requestOptions = new RequestOptions()
        .setAbsoluteURI(webhook)
        .setMethod(HttpMethod.POST);
    httpClient.request(requestOptions).onSuccess(request -> {
      request.putHeader("Content-Type", "application/json")
          .send(message)
          .onFailure(throwable -> log.error("sendDingTalk failed", throwable));
    });
  }

  /**
   * @see SubsMapHelper#remove(String, RegistrationInfo, Promise)
   */
  @SneakyThrows
  private void removeVertxSubs(String address) {
    curator.delete().quietly().deletingChildrenIfNeeded().forPath("/__vertx.subs/" + address);
  }

}
